package com.hashnode.proj0001firstspringsecurity.services;

import com.hashnode.proj0001firstspringsecurity.entities.Otp;
import com.hashnode.proj0001firstspringsecurity.entities.User;
import com.hashnode.proj0001firstspringsecurity.repositories.OtpRepository;
import com.hashnode.proj0001firstspringsecurity.repositories.UserRepository;
import com.hashnode.proj0001firstspringsecurity.utils.GenerateCodeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;
import java.util.logging.Logger;

@Service
@Transactional
public class UserService {

    Logger logger = Logger.getLogger(UserService.class.getName());

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private OtpRepository otpRepository;

    public void addUser(User user) {
        logger.info( String.valueOf( passwordEncoder.encode(user.getPassword()) ));
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userRepository.save(user);
    }

    public void auth(User user) {
        //在数据库中搜索用户
        Optional<User> o =
                userRepository.findUserByUsername(user.getUsername());

        //如果该用户存在，则验证其密码
        if(o.isPresent()) {
            User u = o.get();
            if (passwordEncoder.matches(user.getPassword(), u.getPassword())) {
                //如果密码正确，生成一个新的OTP
                renewOtp(u);
            } else {
                //如果密码不正确或者用户名不存在，则抛出一个异常。
                throw new BadCredentialsException("Bad credentials.");
            }
        } else {
            //如果密码不正确或者用户名不存在，则抛出一个异常。
            throw new BadCredentialsException("Bad credentials.");
        }
    }

    public boolean check(Otp otpToValidate) {
        //按用户名搜索OTP
        Optional<Otp> userOtp = otpRepository.findOtpByUsername(otpToValidate.getUsername());
        //如果数据库中存在OTP，并且与从业务逻辑服务器收到的OTP相同，则返回true。
        if (userOtp.isPresent()) {
            Otp otp = userOtp.get();
            if (otpToValidate.getCode().equals(otp.getCode())) {
                return true;
            }
        }
        //否则，就会返回false。
        return false;
    }

    private void renewOtp(User u) {
        //为OTP生成一个随机值
        String code = GenerateCodeUtil.generateCode();

        //按用户名搜索OTP
        Optional<Otp> userOtp = otpRepository.findOtpByUsername(u.getUsername());
        //如果此用户名存在OTP，更新其值
        if (userOtp.isPresent()) {
            Otp otp = userOtp.get();
            otp.setCode(code);
        } else {
            //如果这个用户名不存在OTP，就用生成的值创建一个新的记录。
            Otp otp = new Otp();
            otp.setUsername(u.getUsername());
            otp.setCode(code);
            otpRepository.save(otp);
        }
    }

}
